//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-4-28
// @Time:下午7:44
//


#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <mhash.h>
#include <iostream>
#include <vector>

// 长参数测试案例
void testGetOptLong(int argc, char *argv[])
{
    int opt; // getopt_long() 的返回值
    int digit_optind = 0; // 设置短参数类型及是否需要参数

    // 如果option_index非空，它指向的变量将记录当前找到参数符合long_opts里的
    // 第几个元素的描述，即是long_opts的下标值
    int option_index = 0;
    // 设置短参数类型及是否需要参数
    const char *optstring = "ab:nr:";

    // 设置长参数类型及其简写，比如 --reqarg <==>-r
    /*
    struct option {
             const char * name;  // 参数的名称
             int has_arg; // 是否带参数值，有三种：no_argument， required_argument，optional_argument
             int * flag; // 为空时，函数直接将 val 的数值从getopt_long的返回值返回出去，
                     // 当非空时，val的值会被赋到 flag 指向的整型数中，而函数返回值为0
             int val; // 用于指定函数找到该选项时的返回值，或者当flag非空时指定flag指向的数据的值
        };
    其中：
        no_argument(即0)，表明这个长参数不带参数（即不带数值，如：--name）
            required_argument(即1)，表明这个长参数必须带参数（即必须带数值，如：--name Bob）
            optional_argument(即2)，表明这个长参数后面带的参数是可选的，（即--name和--name Bob均可）
     */
    static struct option long_options[] = {
            {"reqarg", required_argument, NULL, 'r'},
            {"noarg",  no_argument,       NULL, 'n'},
            {"optarg", optional_argument, NULL, 'o'},
            {0, 0, 0,                           0}  // 添加 {0, 0, 0, 0} 是为了防止输入空值
    };

    while ((opt = getopt_long(argc,
                              argv,
                              optstring,
                              long_options,
                              &option_index)) != -1)
    {
        printf("opt = %c\n", opt); // 命令参数，亦即 -a -b -n -r
        printf("optarg = %s\n", optarg); // 参数内容
        printf("optind = %d\n", optind); // 下一个被处理的下标值
        printf("argv[optind - 1] = %s\n", argv[optind - 1]); // 参数内容
        printf("option_index = %d\n", option_index);  // 当前打印参数的下标值
        printf("\n");
    }
}


void testLogin()
{

}

std::vector<std::string> splitstr(const std::string &str, char tag)
{
    std::vector<std::string> li;
    std::string subStr;

    for (size_t i = 0; i < str.length(); i++)
    {
        if (tag == str[i])
        {
            if (!subStr.empty())
            {
                li.push_back(subStr);
                subStr.clear();
            }
        } else
        {
            subStr.push_back(str[i]);
        }
    }

    if (!subStr.empty())
    {
        li.push_back(subStr);
    }

    return li;
}
typedef char* pchar;

int getParam(std::string &command , pchar *argv)
{
    int i = 0 ;
    char *ptr;
    char *p;
    ptr = strtok_r((char*) command.c_str(), " ", &p);
    while (ptr != NULL)
    {
        argv[i++]=ptr;
        ptr = strtok_r(NULL, " ", &p);
    }
    return i;
}


void login(std::string command)
{
    std::string username;
    std::string password;

    int opt; // getopt_long() 的返回值
    // 如果option_index非空，它指向的变量将记录当前找到参数符合long_opts里的
    // 第几个元素的描述，即是long_opts的下标值
    int option_index = 0;
    // 设置短参数类型及是否需要参数
    const char *optstring = "u:p:";

    static struct option long_options[] = {
            {"username", required_argument, NULL, 'u'},
            {"password",  required_argument, NULL, 'p'},
            {0, 0, 0, 0}  // 添加 {0, 0, 0, 0} 是为了防止输入空值
    };

    // 参数解析
    pchar argv[20];
    int argc = getParam(command , argv);
    while ((opt = getopt_long(argc,
                              argv,
                              optstring,
                              long_options,
                              &option_index)) != -1)
    {
        if(opt == 'u')
        {
            username =std::string(optarg);
        }

        if (opt == 'p')
        {
            password = std::string(optarg);
        }
    }

    std::cout <<"username = "<<username <<" ,  password = " << password<<std::endl;

    return;
}





int main()
{
    std::string command = "login -u aaaa  -p pws";

    login(command);


//
//
//    std::string cmd = "login -u username  -p pws";
//    char *str = (char*) cmd.c_str();
//    char *ptr;
//    char *p;
//
//
//    pchar argv[20];
//
//
//    printf("before strtok:  str=%s\n", str);
//    printf("begin:\n");
//    ptr = strtok_r(str, " ,", &p);
//    int i = 0 ;
//    while (ptr != NULL)
//    {
//        printf("str=%s\n", str);
//        printf("ptr=%s\n", ptr);
//        argv[i++]=ptr;
//        ptr = strtok_r(NULL, " ,", &p);
//
//    }
//
//    std::cout <<"ok"<<std::endl;
//
//
//
//    int opt; // getopt_long() 的返回值
//    int digit_optind = 0; // 设置短参数类型及是否需要参数
//
//    // 如果option_index非空，它指向的变量将记录当前找到参数符合long_opts里的
//    // 第几个元素的描述，即是long_opts的下标值
//    int option_index = 0;
//    // 设置短参数类型及是否需要参数
//    const char *optstring = "u:p:";
////    const char *optstring = "ab:nr:";
//
//    // 设置长参数类型及其简写，比如 --reqarg <==>-r
//    /*
//    struct option {
//             const char * name;  // 参数的名称
//             int has_arg; // 是否带参数值，有三种：no_argument， required_argument，optional_argument
//             int * flag; // 为空时，函数直接将 val 的数值从getopt_long的返回值返回出去，
//                     // 当非空时，val的值会被赋到 flag 指向的整型数中，而函数返回值为0
//             int val; // 用于指定函数找到该选项时的返回值，或者当flag非空时指定flag指向的数据的值
//        };
//    其中：
//        no_argument(即0)，表明这个长参数不带参数（即不带数值，如：--name）
//            required_argument(即1)，表明这个长参数必须带参数（即必须带数值，如：--name Bob）
//            optional_argument(即2)，表明这个长参数后面带的参数是可选的，（即--name和--name Bob均可）
//     */
////    static struct option long_options[] = {
////            {"reqarg", required_argument, NULL, 'r'},
////            {"noarg",  no_argument,       NULL, 'n'},
////            {"optarg", optional_argument, NULL, 'o'},
////            {0, 0, 0,                           0}  // 添加 {0, 0, 0, 0} 是为了防止输入空值
////    };
//
//    static struct option long_options[] = {
//            {"username", required_argument, NULL, 'u'},
//            {"password",  required_argument, NULL, 'p'},
//            {0, 0, 0,                           0}  // 添加 {0, 0, 0, 0} 是为了防止输入空值
//    };
//
//    printf("start\n");
//
//    while ((opt = getopt_long(i,
//                              argv,
//                              optstring,
//                              long_options,
//                              &option_index)) != -1)
//    {
//        printf("opt = %c\n", opt); // 命令参数，亦即 -a -b -n -r
//        printf("optarg = %s\n", optarg); // 参数内容
//        printf("optind = %d\n", optind); // 下一个被处理的下标值
//        printf("argv[optind - 1] = %s\n", argv[optind - 1]); // 参数内容
//        printf("option_index = %d\n", option_index);  // 当前打印参数的下标值
//        printf("\n");
//    }
//
//
//    char test[] = "data \0 dad ";
//    std::string testdata2(test , 12);
//    std::string testData(test);
//    std::cout <<testData <<"len " << sizeof(test) << "==" << testdata2 << "len " << testData.length() << " - " << testdata2.length()<<std::endl;
//    return 0;
}


